#pragma once
#include <sys/epoll.h>

namespace NS_epoll
{
    class Epoll
    {
        static const int gsize=256;
    public:
        // int epoll_create(int size);
        // size:废弃参数,但必须大于零
        static int CreateEpoll()
        {
            return epoll_create(gsize);
        }

        // int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
        // epfd: 需要操作epoll模型的文件描述符
        // op: 对epoll模型的操作选择
        //     1. EPOLL_CTL_ADD: 在文件描述符epfd引用的epoll实例上注册目标文件描述符fd，并将事件事件与链接到fd的内部文件关联起来
        //     2. EPOLL_CTL_MOD: 更改与目标文件描述符fd关联的事件事件
        //     3. EPOLL_CTL_DEL: 从epfd引用的epoll实例中删除(取消注册)目标文件描述符fd
        // event: 
                /*
                typedef union epoll_data 
                {
                    void        *ptr;
                    int          fd;
                    uint32_t     u32;
                    uint64_t     u64;
                } epoll_data_t;

                struct epoll_event 
                {
                    uint32_t     events;   
                    epoll_data_t data;        
                };
                */
        static bool CtlEpoll(int epfd,int op,int sock,uint32_t events)
        {
            struct epoll_event ep_event;
            ep_event.events=events;
            ep_event.data.fd=sock;
            int n = epoll_ctl(epfd,op,sock,&ep_event);

            return 0==n;
        }

        // int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
        // int epfd: 从哪一个epoll模型中的就绪队列中等待
        // struct epoll_event *events: 输出型参数,struct epoll_event events[]
        // int maxevents: 期望获取多少个就绪事件
        // int timeout: 等待时间(阻塞,非阻塞,按时等待)
        static int WaitEpoll(int epfd,struct epoll_event revs[],int num,int timeout)
        {
            // 细节1：如果底层就绪的sock非常多，revs承装不下，怎么办？？不影响！一次拿不完，就下一次再拿
            // 细节2：关于epoll_wait的返回值问题：有几个fd上的事件就绪，就返回几，epoll返回的时候，会将所有就绪的event按照顺序放入到revs数组中！一共有返回值个！
            return epoll_wait(epfd,revs,num,timeout);
        }
    };
}
